package il.technion.cs236369.webserver.handlers;

import il.technion.cs236369.webserver.components.INewWebRequest;
import il.technion.cs236369.webserver.components.ServerUtils;
import il.technion.cs236369.webserver.configuration.IServerConfiguration;
import il.technion.cs236369.webserver.logger.WebServerLog;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.Date;

import org.apache.abdera.Abdera;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.Feed;
import org.apache.abdera.parser.Parser;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;

/**
 * 
 * @author Ofir Haviv and Itamar Talmi
 *
 */
public class FileSystemHandler implements IFileSystemHandler {

	private File baseDiractory;
	private IServerConfiguration serverConfiguration;
	
	private final long MaxFileSize = 64 * 1024;
	
	public FileSystemHandler(IServerConfiguration serverConfiguration, String baseDir, String WelcomFile){
		baseDiractory = new File(baseDir);
		this.serverConfiguration = serverConfiguration;
	}
	
	private Boolean checkForFileAccessControl(File requestedFile) throws IOException{
		return requestedFile.getCanonicalPath().startsWith(baseDiractory.getCanonicalPath());
	}

	@Override
	public void handleRequest(INewWebRequest newWebRequest) {
		File requestedFile = new File(baseDiractory, newWebRequest.getRequestedPath()); 
		try {
			if (checkForFileAccessControl(requestedFile) == false || requestedFile.exists() == false || requestedFile.canRead() == false)
				throw new IOException("Error in the supplied path");
		} catch (IOException e) {
			// The supplied path is bad. need to return error code 404 (PDF page 8 section "Handling Requests").
			WebServerLog.log(this, "Error in the supplied path");
			HttpResponse response = ServerUtils.getBasicHtmlResponse(404, "The supplied url is incorrect or unaccessible.");
			ServerUtils.sendResponseToClient(newWebRequest.getClientConnection(), response);
			return;
		}
		
		if (requestedFile.isDirectory())
			handleDirectory(newWebRequest, requestedFile);
		else
			handleFile(newWebRequest, requestedFile);
	}
	
	private String getFileMimeType(String fileName){
		String extension = null;

		int i = fileName.lastIndexOf('.');
		if (i > 0) {
		    extension = fileName.substring(i+1);
		}
		if (extension == null)
			return extension;
		return serverConfiguration.getMimeType(extension);
	}
	
	private void handleFile(INewWebRequest newWebRequest, File requestedFile){
		WebServerLog.log(this, "Asked for file: " + requestedFile.getAbsolutePath());
		
		if (requestedFile.length() > MaxFileSize){	// Check if the file is too big.
			WebServerLog.log(this, "requested file is too big");
			HttpResponse response = ServerUtils.getBasicHtmlResponse(404, "The size of the requested file " + newWebRequest.getRequestedPath() +" is too big.");
			ServerUtils.sendResponseToClient(newWebRequest.getClientConnection(), response);
			return;
		}
		
		HttpResponse response = ServerUtils.generateNewServerResponse(200);
		response.setHeader(HttpHeaders.CONTENT_LENGTH, Long.valueOf(requestedFile.length()).toString());
		
		String mimeType = getFileMimeType(requestedFile.getName());
		if (mimeType != null)
			response.setHeader(HttpHeaders.CONTENT_TYPE, mimeType);
		response.setEntity(new FileEntity(requestedFile));
		
		ServerUtils.sendResponseToClient(newWebRequest.getClientConnection(), response);
	}
	
	private void handleDirectory(INewWebRequest newWebRequest, File requestedFile){
		WebServerLog.log(this, "Asked for directory: " + requestedFile.getAbsolutePath());
		
		
		//String temp = "<feed xmlns=\"http://www.w3.org/2005/Atom\" xml:lang=\"en-US\" xml:base=\"/folder\"><title type=\"text\">List Directory</title><link href=\"http://example.org/\"/><updated>2013-05-17T21:38:04.227Z</updated><author><name>Ran Koretzki</name></author><id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id><contributor><name>Elad Kravi</name></contributor><entry><title type=\"text\">doc.txt</title></entry><entry><title type=\"text\">pic.jpg</title></entry></feed>";
		String temp = getAtomDirectoryRepresentation(newWebRequest, requestedFile);
		
		
		HttpResponse response = ServerUtils.generateNewServerResponse(200);
		response.setHeader(HttpHeaders.CONTENT_TYPE, "application/atom+xml");
		try {
			response.setEntity(new StringEntity(temp));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ServerUtils.sendResponseToClient(newWebRequest.getClientConnection(), response);
		
		
	}
	
	private String getAtomDirectoryRepresentation(INewWebRequest newWebRequest, File directory){
		Abdera abdera = new Abdera();
		Feed feed = abdera.newFeed();

		feed.setId("tag:example.org,2007:/foo");
		feed.setTitle("List Directory");
		//feed.setSubtitle("Feed subtitle");
		feed.setUpdated(new Date());
		feed.addAuthor("Ofir Haviv");
		feed.addAuthor("Itamar Talmi");
		feed.setLanguage("en-US");
		feed.setBaseUri(newWebRequest.getRequestedPath());
		
		//feed.addLink("http://example.com");
		//feed.addLink("http://example.com/foo","self");

		//for (File file : directory.listFiles()){
		File[] files = directory.listFiles();
		for (int i = 0; i < files.length; i++){
			File file = files[i];
			Entry entry = feed.addEntry();
			entry.setId("id" + i);
			entry.setTitle(file.getName());
		}
		return feed.toString();
	}
	
/*	public static void main(String[] args) throws Exception {
		
		Abdera abdera = new Abdera();
		Feed feed = abdera.newFeed();

		feed.setId("tag:example.org,2007:/foo");
		feed.setTitle("Test Feed");
		feed.setSubtitle("Feed subtitle");
		feed.setUpdated(new Date());
		feed.addAuthor("James Snell");
		feed.addLink("http://example.com");
		feed.addLink("http://example.com/foo","self");

		Entry entry = feed.addEntry();
		entry.setId("tag:example.org,2007:/foo/entries/1");
		entry.setTitle("Entry title");
		entry.setSummaryAsHtml("<p>This is the entry title</p>");
		entry.setUpdated(new Date());
		entry.setPublished(new Date());
		entry.addLink("http://example.com/foo/entries/1");
		System.out.println(feed);
	}*/
	
}
